package com.pisolution.scheduler.core.utils;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import oshi.SystemInfo;
import oshi.hardware.GlobalMemory;
import oshi.hardware.HardwareAbstractionLayer;

import javax.annotation.Nullable;
import java.lang.management.ManagementFactory;
import java.net.InetAddress;
import java.net.UnknownHostException;

/**
 * 操作系统相关辅助交互工具类.
 *
 * @author sora
 * @version 0.1.0
 */
public final class OSUtils {
    private static final Logger LOGGER = LoggerFactory.getLogger(OSUtils.class);

    // -------------------------------------------------------------------------------------------------

    /** 用于获取主机硬件信息. */
    private static final HardwareAbstractionLayer HARDWARE = new SystemInfo().getHardware();

    // -------------------------------------------------------------------------------------------------
    //  网络服务
    // -------------------------------------------------------------------------------------------------

    /**
     * 获取主机网络地址.
     *
     * @return 当前主机网络地址信息 如果无法获取则返回 {@code null}.
     */
    @Nullable
    public static String getHost() {
        try {
            return InetAddress.getLocalHost().getHostAddress();
        } catch (UnknownHostException e) {
            LOGGER.error(e.getMessage(), e);
        }

        return null;
    }

    // -------------------------------------------------------------------------------------------------
    //  资源利用
    // -------------------------------------------------------------------------------------------------

    /**
     * 计算主机一分钟之内的处理器平均负载.
     *
     * @return 一分钟之内主机处理器的平均负载.
     */
    public static double loadAverage() {
        return Double.parseDouble(String.format(
            "%.2f",
            HARDWARE.getProcessor().getSystemLoadAverage(1)[0]
        ));
    }

    /**
     * 计算主机处理器使用率.
     *
     * @param previousCPUTicks 前一次处理器使用率信息.
     *
     * @return 处理器使用率.
     */
    public static double cpuUsage(long[] previousCPUTicks) {
        return Double.parseDouble(String.format(
            "%.2f",
            HARDWARE.getProcessor().getSystemCpuLoadBetweenTicks(previousCPUTicks)
        ));
    }

    /**
     * 计算当前处理器各项性能指标.
     *
     * @return 处理器当前各项性能指标.
     */
    public static long[] cpuTicks() {
        return HARDWARE.getProcessor().getSystemCpuLoadTicks();
    }

    /**
     * 计算当前可用物理内存大小 单位为GB.
     *
     * @return 当前可用物理内存大小.
     */
    public static double availablePhysicalMemory() {
        final GlobalMemory memory = HARDWARE.getMemory();

        return Double.parseDouble(String.format(
            "%.2f",
            (memory.getAvailable() + memory.getVirtualMemory().getSwapUsed()) / 1_073_741_824.0
        ));
    }

    /**
     * 计算主机内存使用率.
     *
     * @return 主机内存使用率.
     */
    public static double memoryUsage() {
        final GlobalMemory memory = HARDWARE.getMemory();

        return Double.parseDouble(String.format(
            "%.2f",
            (memory.getTotal() - memory.getAvailable() - memory.getVirtualMemory().getSwapUsed()) * 0.1 / memory.getTotal() * 10
        ));
    }

    // -------------------------------------------------------------------------------------------------
    //  应用程序
    // -------------------------------------------------------------------------------------------------

    /**
     * 获取当前程序进程号.
     *
     * @return 当前程序进程号.
     */
    public static int getProcessID() {
        return Integer.parseInt(ManagementFactory.getRuntimeMXBean().getName().split("@")[0]);
    }

    // -------------------------------------------------------------------------------------------------

    /** 阻止实例化. */
    private OSUtils() {
    }
}
